#pragma once

#include <atlstr.h>

#define AUTO_LOCK(x)	\
		CAutoLock lock(x);

class CSpinLock
{
public:
	CSpinLock()
	{
		CSpinLock(0);	
	}

	CSpinLock(unsigned long SpinCount) : m_nSpinCount(SpinCount)
	{
		memset(&m_sec, 0, sizeof(CRITICAL_SECTION));
	}

	void Lock()
	{
		EnterCriticalSection(&m_sec);
	}

	bool IsLock()
	{
		if (TryEnterCriticalSection(&m_sec) == 0) // owned by another thread
			return false;
		else
		{
			Unlock();
			return true;
		}
	}

	void Unlock()
	{
		LeaveCriticalSection(&m_sec);
	}

	bool TryLock()
	{
		return TryEnterCriticalSection(&m_sec) != 0 ? true : false;
	}

	void Init()
	{
		InitializeCriticalSectionAndSpinCount(&m_sec, m_nSpinCount);
	}

	void Term()
	{
		DeleteCriticalSection(&m_sec);
	}

	operator CRITICAL_SECTION&()
	{
		return m_sec;
	}

private:
	unsigned long	 m_nSpinCount;
	CRITICAL_SECTION m_sec;
};

class CAutoSpinLock : public CSpinLock
{
public:
	CAutoSpinLock() : CSpinLock(m_nSpinCount)
	{
		__super::Init();
	}

	~CAutoSpinLock()
	{
		__super::Term();
	}

private:
	void Init();
	void Term(); 

private:
	static const unsigned long m_nSpinCount = 1000;
};

class CAutoLock
{
public:
	CAutoLock( CRITICAL_SECTION& cs )
	{
		m_pcs = &cs;

		EnterCriticalSection( m_pcs );
	}

	~CAutoLock()
	{
		LeaveCriticalSection( m_pcs );
	}

	LPCRITICAL_SECTION m_pcs;
};

//simulator aouto loack for safe power switch
//when enter, power switch off 
//when exit, power switch on
class CPowerSwitchAutoLock
{
public:
	CPowerSwitchAutoLock( CRITICAL_SECTION& cs , bool& bSwitchOn)
	{
		m_pcs = &cs;
		m_pSwitch = &bSwitchOn;

		EnterCriticalSection( m_pcs );
		*m_pSwitch = false;
	}

	~CPowerSwitchAutoLock()
	{
		LeaveCriticalSection( m_pcs );
		*m_pSwitch = true;
	}
private:
	bool* m_pSwitch;
	LPCRITICAL_SECTION m_pcs;
};
